package com.torry.replay.api.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.torry.replay.api.request.AnalyzeLimitUpInfoRequest;
import com.torry.replay.api.request.SaveLimitUpInfoRequest;
import com.torry.replay.api.result.GetLimitUpInfoResult;
import com.torry.replay.infras.entity.DragonDO;
import com.torry.replay.infras.entity.LimitUpDO;
import com.torry.replay.infras.repo.DragonRepository;
import com.torry.replay.infras.repo.LimitUpRepository;
import com.torry.replay.infras.repo.TagRepository;
import com.torry.replay.integration.StockApi;
import com.torry.replay.integration.result.SyncLimitUpResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author torry.wang
 */
@RestController
@RequestMapping("/limit")
@Api(tags = "涨停板行情")
@CrossOrigin
public class LimitUpController {

    @Resource
    private LimitUpRepository limitUpRepository;
    @Resource
    private TagRepository tagRepository;
    @Resource
    private StockApi stockApi;
    @Resource
    private DragonRepository dragonRepository;

    @GetMapping("syncLimitInfos/{date}")
    @ApiOperation(value = "从东方财富同步涨停板信息")
    public List<SyncLimitUpResult> syncLimitInfos(@PathVariable String date) {
        return stockApi.getLimitUpList(date);
    }

    @GetMapping("getLogicsByDate/{date}")
    @ApiOperation(value = "获取涨停逻辑下拉列表")
    public Set<String> getLogicsByDate(@PathVariable String date) {
        List<LimitUpDO> list = limitUpRepository.list(new LambdaQueryWrapper<LimitUpDO>().eq(LimitUpDO::getDate, date));
        Set<String> logicSet = new HashSet<>();
        list.forEach(e -> {
            String logic = e.getLogic();
            if (StringUtils.isNotBlank(logic)) {
                String[] split = logic.split(",");
                logicSet.addAll(Arrays.asList(split));
            }
        });
        return logicSet;
    }


    @PostMapping("saveLimitUpInfo")
    @ApiOperation(value = "保存涨停板列表")
    public Boolean saveLimitUpInfo(@RequestBody SaveLimitUpInfoRequest request) {

        List<SaveLimitUpInfoRequest.LimitUpInfo> list = request.getList();
        List<Long> existIds = list.stream().filter(e -> e.getId() != null).map(SaveLimitUpInfoRequest.LimitUpInfo::getId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(existIds)) {
            List<Long> ids = limitUpRepository.listObjs(new LambdaQueryWrapper<LimitUpDO>().eq(LimitUpDO::getDate, request.getDate()).select(LimitUpDO::getId), e -> Long.parseLong(String.valueOf(e)));
            if (CollectionUtils.isNotEmpty(ids)) {
                ids.removeAll(existIds);
                if (CollectionUtils.isNotEmpty(ids)) {
                    limitUpRepository.removeByIds(ids);
                }
            }
        }

        List<LimitUpDO> dos = list.stream().map(e -> {
            LimitUpDO limitUpDO = new LimitUpDO();
            limitUpDO.setDate(request.getDate());
            limitUpDO.setName(e.getName());
            limitUpDO.setPrice(e.getPrice());
            limitUpDO.setQuantity(e.getQuantity());
            limitUpDO.setIncreaseRange(e.getIncreaseRange());
            limitUpDO.setMarketValue(e.getMarketValue());
            limitUpDO.setVolume(e.getVolume());
            limitUpDO.setTurnoverRate(e.getTurnoverRate());
            limitUpDO.setLimitTime(e.getLimitTime());
            limitUpDO.setLastLimitTime(e.getLastLimitTime());
            limitUpDO.setBombCount(e.getBombCount());
            limitUpDO.setStat(e.getStat());
            limitUpDO.setContinuousCount(e.getContinuousCount());
            if (CollectionUtils.isNotEmpty(e.getLogics())) {
                limitUpDO.setLogic(String.join(",", e.getLogics()));
            }
            limitUpDO.setTagId(e.getTagId());
            limitUpDO.setId(e.getId());
            return limitUpDO;
        }).collect(Collectors.toList());

        return limitUpRepository.saveOrUpdateBatch(dos);
    }

    @PostMapping("analyzeLimitUpInfo")
    @ApiOperation(value = "涨停板数据分析")
    public GetLimitUpInfoResult analyzeLimitUpInfo(@RequestBody AnalyzeLimitUpInfoRequest request) {

        LambdaQueryWrapper<LimitUpDO> wrapper = new LambdaQueryWrapper<LimitUpDO>().eq(LimitUpDO::getDate, request.getDate());
        if (CollectionUtils.isNotEmpty(request.getLogics())) {
            wrapper.and(childWrapper -> {
                request.getLogics().forEach(e -> {
                    childWrapper.or().like(LimitUpDO::getLogic, e);
                });
            });
        }
        if (CollectionUtils.isNotEmpty(request.getSortColumns())) {
            request.getSortColumns().forEach(column -> {
                wrapper.orderByDesc(column.equals("continuousCount"), LimitUpDO::getContinuousCount)
                        .orderByAsc(column.equals("bombCount"), LimitUpDO::getBombCount)
                        .orderByAsc(column.equals("limitTime"), LimitUpDO::getLimitTime)
                        .orderByAsc(column.equals("marketValue"), LimitUpDO::getMarketValue)
                        .orderByAsc(column.equals("price"), LimitUpDO::getPrice);
            });
        }


        List<LimitUpDO> limitUps = limitUpRepository.list(wrapper);
        GetLimitUpInfoResult result = new GetLimitUpInfoResult();
        result.setList(buildLimitUpInfo(limitUps));
        return result;
    }


    @GetMapping("getLimitUpInfo/{date}")
    @ApiOperation(value = "获取涨停板数据")
    public List<LimitUpDO> getLimitUpInfo(@PathVariable String date) {
        List<LimitUpDO> limitUps = limitUpRepository.list(new LambdaQueryWrapper<LimitUpDO>().eq(LimitUpDO::getDate, date));
        limitUps.forEach(e -> e.setTagName(tagRepository.getById(e.getTagId()).getName()));
        return limitUps;
    }

    public List<GetLimitUpInfoResult.LimitUpInfo> buildLimitUpInfo(List<LimitUpDO> limitUps) {
        if (CollectionUtils.isEmpty(limitUps)) return Collections.emptyList();
        LocalDate date = limitUps.get(0).getDate();
        LocalDate nextDay = limitUpRepository.getNextDay(date);
        List<String> nextLimitUpNames = new ArrayList<>();
        if (nextDay != null) {
            nextLimitUpNames = limitUpRepository.list(new LambdaQueryWrapper<LimitUpDO>().eq(LimitUpDO::getDate, nextDay)).stream().map(LimitUpDO::getName).collect(Collectors.toList());
        }
        List<String> finalNextLimitUpNames = nextLimitUpNames;
        return limitUps.stream().map(e -> {
            GetLimitUpInfoResult.LimitUpInfo info = new GetLimitUpInfoResult.LimitUpInfo();
            info.setId(e.getId());
            info.setName(e.getName());
            info.setPrice(e.getPrice());
            info.setQuantity(e.getQuantity());
            info.setIncreaseRange(e.getIncreaseRange());
            info.setMarketValue(e.getMarketValue());
            info.setSealAmount(e.getSealAmount());
            info.setVolume(e.getVolume());
            info.setTurnoverRate(e.getTurnoverRate());
            info.setLimitTime(e.getLimitTime());
            info.setLastLimitTime(e.getLastLimitTime());
            info.setBombCount(e.getBombCount());
            info.setStat(e.getStat());
            info.setContinuousCount(e.getContinuousCount());
            info.setLogic(e.getLogic());
            info.setTagName(e.getName());
            info.setInterrupted(0);
            int dragonCount = dragonRepository.count(new LambdaQueryWrapper<DragonDO>().eq(DragonDO::getDate, e.getDate()).eq(DragonDO::getName, e.getName()));
            info.setHasDragon(dragonCount > 0 ? 1 : 0);
            if (nextDay != null) {
                info.setInterrupted(finalNextLimitUpNames.contains(e.getName()) ? 0 : 1);
            }
            if (e.getTagId() != null) {
                String tagName = tagRepository.getById(e.getTagId()).getName();
                info.setTagName(tagName);
            }
            return info;
        }).collect(Collectors.toList());
    }

    @GetMapping("getPreviousDay/{date}")
    @ApiOperation(value = "获取前一天日期")
    public String getPreviousDay(@PathVariable @ApiParam(value = "当前日期") String date) {
        LocalDate previousDay = limitUpRepository.getPreviousDay(LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        return previousDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }
}
